/*
 * Copyright 2011-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0.
 * See `LICENSE` in the project root for license information.
 */

package me.ijleex.mgmt.commons.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 集合工具类
 *
 * <p>得到两个集合的交集，List累加，得到Map的值等。</p>
 *
 * @author liym
 * @since 2018-06-07 17:30 新建
 */
public final class CollectionUtils {

    private CollectionUtils() {}

    /**
     * 计算两个集合的交集
     *
     * @param c1 集合1
     * @param c2 集合2
     * @param <T> 集合中的元素的类型
     * @return 两个集合的交集： collection1 ∩ collection2
     * @see List#retainAll(Collection)
     * @since 2014-04-14 09:48:05
     */
    public static <T> Collection<T> getIntersection(Collection<T> c1, Collection<T> c2) {
        Set<T> resultSet = new HashSet<>();
        if (null == c1 || null == c2 || c1.isEmpty() || c2.isEmpty()) {
            return resultSet;
        }
        CollectionCouple<T> couple = getCouple(c1, c2);
        Set<T> set = (Set<T>) couple.reference;
        for (T t : couple.contrast) {
            if (set.contains(t)) {
                resultSet.add(t);
            }
        }
        return resultSet;
    }

    private static <T> CollectionCouple<T> getCouple(Collection<T> collection1, Collection<T> collection2) {
        CollectionCouple<T> couple = new CollectionCouple<T>();
        boolean larger = collection1.size() > collection2.size();
        if (collection1 instanceof Set<?> && collection2 instanceof Set<?>) {
            couple.reference = larger ? collection1 : collection2;
            couple.contrast = larger ? collection2 : collection1;
            couple.hasSet = true;
        } else if (collection1 instanceof Set<?>) {
            couple.reference = collection1;
            couple.contrast = collection2;
            couple.hasSet = true;
        } else if (collection2 instanceof Set<?>) {
            couple.reference = collection2;
            couple.contrast = collection1;
            couple.hasSet = true;
        } else {
            couple.reference = larger ? collection2 : collection1;
            couple.contrast = larger ? collection1 : collection2;
        }
        couple.reference = couple.hasSet ? (Set<T>) couple.reference : new HashSet<T>(couple.reference);
        return couple;
    }

    /**
     * 累加List的值（Accumulate）
     *
     * <p>适用于表格列的值累加</p>
     *
     * @param amtList 表格列的值
     * @param <T> List中的元素的类型
     * @return List的值的累加之和
     * @since 2014-04-15 21:20:54
     */
    public static <T> String sum(List<T> amtList) {
        if (amtList == null) {
            return "";
        }
        String sum = "0";
        for (T val : amtList) {
            String ss = val.toString();
            sum = MathUtils.add(sum, ss);
        }
        return String.valueOf(sum);
    }

    /**
     * 过滤 List 中的 NULL 值
     *
     * @param columnList 表格列的数据
     * @return list
     * @since 2014-04-16 11:16:35
     */
    public static List<Object> nullFilter(List<Object> columnList) {
        List<Object> nonNullList = new ArrayList<>();

        for (Object ss : columnList) {
            if (null == ss) {
                ss = "";
            }
            nonNullList.add(ss);
        }
        return nonNullList;
    }

    /**
     * 根据 Map 的键值对过滤出 List 中包含 Map 的对象中符合条件的列表
     *
     * @param mapList 待过滤的List对象
     * @param mapKey Map的键
     * @param mapValue Map的键对应的值
     * @return 过滤出的符合条件的列表
     * @throws Exception 可能出现的异常
     * @since 2014-06-06 09:52:28
     */
    public static List<Map<String, Object>> mapListFilter(List<Map<String, Object>> mapList, String mapKey, String mapValue)
            throws Exception {
        List<Map<String, Object>> subList = new ArrayList<Map<String, Object>>();

        if (mapList == null || mapList.isEmpty()) {
            return subList;
        }

        try {
            for (Map<String, Object> map : mapList) {
                String val = (String) map.get(mapKey);
                if (val.equals(mapValue)) {
                    subList.add(map);
                }
            }
        } catch (Exception e) {
            throw new Exception("Map中不含该键：" + mapKey);
        }
        return subList;
    }

    /**
     * 从 Map 中获取到 {@code key} 对应的值
     *
     * <p>如果 Map 为 null，或者 Map 不包含 {@code key}，则抛异常</p>
     *
     * @param map Map
     * @param key 键名
     * @return key对应的值
     * @throws Exception 可能发生的异常
     * @author liym
     * @since 2014-12-11 17:30:33
     */
    public static <K, V> Object getMapValue(Map<K, V> map, K key) throws Exception {
        Object retVal;
        if (map == null) {
            throw new Exception("Map不能为null");
        } else {
            if (!map.containsKey(key)) {
                // throw new Exception("Map中不存在该键：" + key);
                retVal = "";
            } else {
                Object o = map.get(key);
                retVal = o == null ? "" : o;
            }
        }
        return retVal;
    }

    /**
     * 求集合的交集
     *
     * @param c1 集合1
     * @param c2 集合2
     * @author liym
     * @see List#retainAll(Collection)
     * @see #getIntersection(java.util.Collection, java.util.Collection)
     * @since 交集
     * @since 2015-05-29 15:06:53
     */
    public static <T> Collection<T> calcIntersection2(Collection<T> c1, Collection<T> c2) {
        List<T> list1 = new ArrayList<T>(c1);
        List<T> list2 = new ArrayList<T>(c2);
        list1.retainAll(list2);
        return list1;
    }

    public static void main(String[] args) {
        String[] c1 = new String[]{"0", "3", "5", "7", "8", "12", "2"};
        String[] c2 = new String[]{"1", "4", "6", "7", "8", "10"};

        Collection<String> identicalValues = getIntersection(Arrays.asList(c1), Arrays.asList(c2));
        System.out.println(identicalValues);

        Collection<String> calcIntersection = calcIntersection2(Arrays.asList(c1), Arrays.asList(c2));
        System.out.println(calcIntersection);
    }

}
